/*
 * Manager.h
 *
 *  Created on: 2011/06/04
 *      Author: naoki
 */

#ifndef INCLUDED_NTENGINE_GRAPHICS_MANAGER_H
#define INCLUDED_NTENGINE_GRAPHICS_MANAGER_H

#include "NTEngine/Graphics/Enum.h"

namespace NTEngine {

namespace Math {
class Matrix4x4;
class Matrix3x4;
class Vector2;
class Vector3;
} // namespace Math
using namespace Math;

/**
 * @brief Graphicsモジュール
 */
namespace Graphics {
class Texture;
class VertexBuffer;
class IndexBuffer;

/**
 * @brief グラフィックスのマネージャです
 * GPUへのデータ転送などを統括します
 */
class Manager {
public:
	/**
	 * Managerインスタンスを取得します
	 * これはinstance()と同じ動作をします
	 */
	Manager();

	/**
	 * Managerインスタンスを取得します
	 */
	static Manager instance();

	/**
	 * デプステストを行うか設定します
	 * デフォルトの設定はtrueです
	 */
	void enableDepthTest( bool );

	/**
	 * デプスバッファへの書き込みをするか設定します
	 * デフォルトの設定はtrueです
	 */
	void enableDepthWrite( bool );

	/**
	 * ブレンドモードの設定をします
	 * デフォルトはBLEND_OPAQUEです
	 */
	void setBlendMode( BlendMode );

	/**
	 * カリングモードの設定をします
	 * デフォルトはCULL_BACKです
	 */
	void setCullMode( CullMode );

	/**
	 * テクスチャフィルタを設定します
	 * デフォルトはTEXF_POINTです
	 */
	void setTextureFilter( TextureFilter );

	/**
	 * VertexBufferを設定します
	 */
	void setVertexBuffer( VertexBuffer );

	/**
	 * IndexBufferを設定します
	 */
	void setIndexBuffer( IndexBuffer );

	/**
	 * Textureを設定します
	 */
	void setTexture( Texture );

	/**
	 * 透視変換ビュー変換行列セット
	 */
	void setProjectionViewMatrix( const Matrix4x4& );

	/**
	 * ワールド変換行列セット
	 */
	void setWorldMatrix( const Matrix3x4& );

	/**
	 * ビューポートを設定します
	 */
	void setViewport( int x, int y, int width, int height );

	/**
	 * ビューポートを取得します
	 * (NULLでないものにだけ入れるので欲しいものだけポインタをセット)
	 */
	void getViewport( int* oX, int* oY, int* oWidth, int* oHeight );

	/**
	 * エフェクトグループを変更
	 */
	void setLightingMode( LightingMode );

	/**
	 * ライト位置
	 */
	void setLightPosition( int index, const Vector3& position );

	/**
	 * ライト強度(100なら100mの距離で1の明るさになる。強度Iとして、明るさは「I/距離」で決まる)
	 */
	void setLightIntensity( int index, float intensity );

	/**
	 * ライト色
	 */
	void setLightColor( int index, const Vector3& );

	/**
	 * 視点位置
	 */
	void setEyePosition( const Vector3& position );

	/**
	 * ディフューズカラー
	 */
	void setDiffuseColor( const Vector3& );

	/**
	 * スペキュラ色
	 */
	void setSpecularColor( const Vector3& );

	/**
	 * 発光色
	 */
	void setEmissionColor( const Vector3& );

	/**
	 * アンビエント色
	 */
	void setAmbientColor( const Vector3& );

	/**
	 * 透明度設定
	 */
	void setTransparency( float );

	/**
	 * スペキュラの鋭さ(大きいほど鋭い)
	 */
	void setSpecularSharpness( float );

	/**
	 * フレームIDを取得します
	 */
	unsigned frameId() const;

	/**
	 * @brief プリミティブの描画をします
	 */
	void draw( int offset, int primitiveNumber, PrimitiveType type );

	/**
	 * @brief インデックス付きプリミティブの描画をします
	 */
	void drawIndexed( int offset, int primitiveNumber, PrimitiveType type );

	/**
	 * 描画領域の横幅を取得します
	 */
	int width() const;

	/**
	 * 描画領域の高さを取得します
	 */
	int height() const;

	/**
	 * フルスクリーン時のウィンドウ幅を返します
	 * (width()と同じ動作をします)
	 */
	int fullScreenWindowWidth() const;

	/**
	 * フルスクリーン時のウィンドウ高さを返します
	 * (height()と同じ動作をします)
	 */
	int fullScreenWindowHeight() const;

// ----------------- 以下はシステム側で使用します -----------------

	/**
	 * グラフィックスモジュールを生成・初期化します
	 */
	static void create( void*, int, int, bool, bool, bool, bool, bool, bool );

	/**
	 * グラフィックスモジュールを破棄します
	 */
	static void destroy();

	/**
	 * レストア処理を行います
	 * プラットフォームによって処理は様々ですが、基本的にGPUへのインターフェースのリセットを行います
	 */
	void restore();

	/**
	 * GPUへのインターフェースを強制的に破棄します
	 * プラットフォームによってはcanRender()がfalseを返したときにコールしてください。
	 */
	void release();

	/**
	 * 画面が変更された際にコールします
	 * 変更後の画面情報で再設定します
	 */
	void changeDisplayMode( bool );

	/**
	 * 描画処理の開始時にコールします
	 */
	void beginRender();

	/**
	 * 描画処理の終了時にコールします
	 */
	void endRender();

	/**
	 * 描画が可能な状態であるか問い合わせます
	 */
	bool canRender() const;
};

} // namespace Graphics
} // namespace NtEngine

#endif // INCLUDED_NTENGINE_GRAPHICS_MANAGER_H
